package userserv

import (
	"codedef"
	"encoding/json"
	"github.com/garyburd/redigo/redis"
	"log"
	"net/http"
	"rhelper"
	"strconv"
)

type SetModeAction struct {
	Cid    string `json:"cid"`
	Switch string `json:"switch"`
}

type RuntimeInfo struct {
	PowerState       string  `json:"powerState"`
	ScreenSleepState string  `json:"screenSleepState"`
	AutoState        string  `json:"autoState"`
	Pwm              int     `json:"pwm"`
	SpeedLeve        int     `json:"speedLeve"`
	Aqi              int     `json:"aqi"`
	FilterUseTime    int     `json:"filterUseTime"`
	FilterLife       float64 `json:"filterLife"`
	PreFanSpeed      int     `json:"preFanSpeed"`
}

func GetMaxPwm(w http.ResponseWriter, cid string) int {
	rconn := rhelper.Pool().Get()
	defer rconn.Close()

	maxPwm, err := redis.String(rconn.Do("HGET",
		rhelper.ControllerHash+cid,
		"maxPwm"))
	if err != nil {
		log.Println("get maxpwm failed, error: ", err)
		replyError(w, codedef.ERR_DATABASE)
		return -1
	}

	maxPwm_int, err := strconv.Atoi(maxPwm)
	return maxPwm_int
}

func convertPwm2Speed(pwm int) int {
	switch {
	case pwm == 630:
		return 1
	case pwm == 800:
		return 2
	case pwm == 980:
		return 3
	case pwm == 270:
		return 4
	default:
		return -1
	}
}

func processDevMessage(w http.ResponseWriter, wait []byte) ([]byte, bool) {

	type ReturnValue struct {
		Uri         string `json:"uri"`
		PreFanSpeed int    `json:"preFanSpeed"`
		PreFanLevel int    `json:"preFanLevel"`
		Error       int    `json:"error"`
		MoonState   string `json:"moonState"`
		AutoState   string `json:"autoState"`
	}

	devMessage, errCode := parserDevReply(wait)
	if 0 != errCode {
		replyError(w, codedef.ERR_OPRATION_FAILD)
		return nil, true
	}

	var returnValue ReturnValue
	err := json.Unmarshal(devMessage, &returnValue)
	if err != nil {
		log.Println("setModeAuto failed, json decode failed:", err)
		replyError(w, codedef.ERR_DECODE)
		return nil, true
	}

	if returnValue.Error != 0 {
		replyError(w, codedef.ERR_OPRATION_FAILD)
	}

	returnValue.PreFanLevel = convertPwm2Speed(returnValue.PreFanSpeed)

	msgBuf, err := json.Marshal(returnValue)
	if err != nil {
		log.Println("setModeAuto failed, json encode failed:", err)
		replyError(w, codedef.ERR_ENCODE)
		return nil, true
	}

	return msgBuf, false

}

func setModeAuto(w http.ResponseWriter,
	controller *Controller,
	modeSwitch string,
	responseFlag bool) bool {

	type Message struct {
		Uri    string `json:"uri"`
		Action string `json:"action"`
	}

	msg := Message{}
	msg.Uri = "/auto"
	msg.Action = modeSwitch

	// log.Println("messgae: ", msg)

	if wait := syn2Device(*controller, msg); wait != nil {
		// log.Println("start to reply app.", string(wait))

		if responseFlag {
			devMessage, returnFlag := processDevMessage(w, wait)
			if returnFlag {
				return true
			}

			replyBuffer(w, devMessage)
			return true
		}
		return false

	} else {
		log.Println("setModeAuto failed, syn2Device error")
		replyError(w, codedef.ERR_CONTROLLER_NO_RESPONSE)
		return true
	}
}

func setModeSleep(w http.ResponseWriter,
	controller *Controller,
	modeSwitch string,
	//runTimeInfo *RuntimeInfo,
	responseFlag bool) bool {

	type Message struct {
		Uri    string `json:"uri"`
		Action string `json:"action"`
	}

	msg := Message{}
	msg.Uri = "/moon"
	msg.Action = modeSwitch

	/*if modeSwitch == "on" {
	      msg.Pwm = maxPwm_int / 5
	  } else {
	      msg.Pwm = runTimeInfo.PreFanSpeed
	  }*/

	log.Println("messge: ", msg)

	if wait := syn2Device(*controller, msg); wait != nil {
		//log.Println("start to reply app.", string(wait))

		if responseFlag {
			devMessage, returnFlag := processDevMessage(w, wait)
			if returnFlag {
				return true
			}

			replyBuffer(w, devMessage)
			return true
		}

		return false

	} else {
		log.Println("save setModeSleep, syn2Device failed")
		replyError(w, codedef.ERR_CONTROLLER_NO_RESPONSE)
		return true
	}
}

func setMode(w http.ResponseWriter, r *http.Request) {
	var uniqueId string
	uniqueId = r.Header.Get("uniqueId")

	log.Printf("setMode, uniqueId:%s\n", uniqueId)

	message := make([]byte, r.ContentLength)
	n, _ := r.Body.Read(message)
	if n != int(r.ContentLength) {
		log.Println("setMode failed, can't read request body")
		replyError(w, codedef.ERR_REQUEST_INVALID_PARAM)
		return
	}

	var action SetModeAction
	err := json.Unmarshal(message, &action)
	if err != nil {
		log.Println("setMode failed, json decode failed:", err)
		replyError(w, codedef.ERR_DECODE)
		return
	}

	errCode := checkDevCtrlAction(action.Cid, uniqueId)
	if errCode != codedef.ERR_SUCCEED {
		log.Println("setMode failed, check task error:", err)
		replyError(w, codedef.ERR_OPRATION_FAILD)
		return
	}

	controller := getOnlineControllerById(action.Cid)
	if controller == nil {
		log.Println("syncPlan2Device failed, no online controller for:",
			action.Cid)
		replyError(w, codedef.ERR_CONTROLLER_OFFLINE)
		return
	}

	if controller.isBusy() {
		log.Println("syncPlan2Device failed, controller is busy:", action.Cid)
		replyError(w, codedef.ERR_CONTROLLER_BUSY)
		return
	}

	//runTimeInfo := GetRuntimeInfo(w, controller)
	//if runTimeInfo == nil {
	//    return
	//}

	switch r.URL.Path {
	case "/setModeAuto":
		//if runTimeInfo.Pwm <= maxPwm_int / 5 {
		//    returnFlag := setModeSleep(w, controller,
		//                               "off",
		//                               maxPwm_int,
		//                               runTimeInfo,
		//                               false)
		//
		//    if returnFlag {
		//        return
		//    }
		//}
		setModeAuto(w, controller, action.Switch, true)
	case "/setModeSleep":
		//if runTimeInfo.AutoState == "on" {
		//    returnFlage := setModeAuto(w, controller,
		//                               "off",
		//                               maxPwm_int,
		//                               false)
		//
		//    if returnFlage {
		//        return
		//    }
		//}
		setModeSleep(w, controller,
			action.Switch,
			//runTimeInfo,
			true)
	}
	//go GetRuntimeInfo(w, controller)
}

func init() {
	myMux.muxHandlers.HandleFunc("/setModeAuto", setMode)
	myMux.muxHandlers.HandleFunc("/setModeSleep", setMode)
}
